/**
 * ReportGear(2011)
 */
package com.reportgear.report.view.grid;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.reportgear.report.core.api.compare.ComparatorUtils;
import com.reportgear.report.model.ReportModel;
import com.reportgear.report.model.auxiliary.ColumnPropList;
import com.reportgear.report.model.auxiliary.ColumnRow;
import com.reportgear.report.model.auxiliary.RowPropList;
import com.reportgear.report.model.cell.Cell;
import com.reportgear.report.model.cell.DefaultCell;
import com.reportgear.report.view.JWorksheet;
import com.reportgear.report.view.grid.editor.CellEditorEvent;
import com.reportgear.report.view.grid.editor.CellEditorListener;
import com.reportgear.report.view.grid.editor.CellEditor;
import com.reportgear.report.view.grid.selection.GridSelection;
import com.reportgear.report.view.grid.selection.Selection;
import com.reportgear.report.view.grid.util.GraphHelper;
import com.reportgear.report.view.grid.util.GridUtils;
import com.reportgear.report.view.grid.util.KeyEventUtils;
import com.reportgear.report.view.util.WorksheetUtils;

/**
 * 编辑GRID
 * 
 * @version 1.0 2011-3-18
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 * 
 */
public class Grid extends BaseGridComponent {
	private static final Logger logger = LoggerFactory.getLogger(Grid.class.getName());
	// 拖动刷新时间
	private static final int DRAG_REFRESH_TIME = 100;
	// 移动刷新时间
	private static final int MOVE_REFRESH_TIME = 100;
	// 是否显示网格线
	private boolean showGridLine = true;
	// 功能弹出菜单
	private JPopupMenu gridActionMenu;
	// 网格线颜色
	private Color gridLineColor = Color.LIGHT_GRAY;
	// 显示分页线
	private boolean showPaginateLine = true;
	// 显示强制分页线
	private boolean showForcedPaginateLine = true;
	// 分页线颜色
	private Color paginationLineColor = Color.RED;
	// 选中背景颜色
	private Color selectedBackground = new Color(150, 150, 255);
	// 选中边框颜色
	private Color selectedBorderLineColor = Color.BLACK;
	// 是否可编辑
	private boolean editable = true;
	// 单元格是否可选择
	private boolean cellSelectable = true;
	// 支持单元格编辑
	private boolean supportCellEditorDef = false;
	// 单元格可以编辑
	private boolean cellDragable = true;

	private long lastMouseMoveTime = 0L;

	int oldEvtX = 0;
	int oldEvtY = 0;
	int oldLocationX = 0;
	int oldLocationY = 0;
	private int dragType = GridUtils.DRAG_NONE;
	private Rectangle dragRectangle = null;
	private String tooltipText = null;
	private Point tooltipLocation = new Point();
	private int tabMoveDirection = 0;
	private int enterMoveDirection = 0;
	// private Calculator calculator = new Calculator();
	private transient Component editorComponent;
	/**
	 * 当前正在编辑的单元格对象
	 */
	private transient Cell editingCell;
	/**
	 * 编辑器
	 */
	protected transient CellEditor cellEditor;
	protected transient int editingColumn;
	protected transient int editingRow;
	private long keyPressedLastTime = 0L;
	private boolean isKeyPressedContentChanged = false;
	static int ToolTipLeftDistance = 12;
	// private List paintCellElementList = new ArrayList();
	// private List paintCellElementRectangleList = new ArrayList();
	// private List clipCellElementRectangleList = new ArrayList();
	// private List paperMarginLineList = new ArrayList();
	// private List forcedPaperMarginLineList = new ArrayList();
	// 是否正在绘制
	private boolean isPainting = false;
	// 是否数据改变
	private boolean isDataChanged = false;
	// private static BackgroundInterface WHITE_Backgorund =
	// ColorBackground.getInstance(Color.WHITE);
	// private static BackgroundInterface LIGHT_Backgorund =
	// ColorBackground.getInstance(new Color(250, 250, 250));
	// 临时绘制对象
	private Rectangle2D tmpRectangle2D = new Rectangle2D.Double(0.0D, 0.0D, 0.0D, 0.0D);

	private GridAction gridAction;

	private CellEditorListener innerCellEditorListener = new CellEditorListener() {

		public void editingStopped(CellEditorEvent evt) {
			Grid.this.stopCellEditingInner(false);
		}

		public void editingCanceled(CellEditorEvent evt) {
			Grid.this.cancelEditing();
		}
	};

	public Grid(JWorksheet workSheet) {
		super(workSheet);

		this.enableEvents(KeyEvent.MOUSE_EVENT_MASK + KeyEvent.MOUSE_MOTION_EVENT_MASK + KeyEvent.KEY_EVENT_MASK
				+ KeyEvent.MOUSE_WHEEL_EVENT_MASK);

		// TODO 怎么处理
		gridAction = new GridAction(this);

		setFocusTraversalKeysEnabled(false);
		setOpaque(false);
		ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
		toolTipManager.registerComponent(this);
		toolTipManager.setInitialDelay(1);
		toolTipManager.setReshowDelay(1);
		toolTipManager.setDismissDelay(180000);
	}

	public boolean isShowGridLine() {
		return this.showGridLine;
	}

	public void setShowGridLine(boolean showGridLine) {
		this.showGridLine = showGridLine;
		this.worksheet.refresh();
	}

	public Color getGridLineColor() {
		return this.gridLineColor;
	}

	public void setGridLineColor(Color color) {
		Color oldColor = this.gridLineColor;
		this.gridLineColor = color;

		this.firePropertyChange("gridLineColor", oldColor, this.gridLineColor);
		this.repaint();
	}

	public boolean isShowPaginateLine() {
		return this.showPaginateLine;
	}

	public void setShowPaginateLine(boolean showPaginateLine) {
		this.showPaginateLine = showPaginateLine;
		this.worksheet.updateUI();
	}

	public Color getPaginationLineColor() {
		return this.paginationLineColor;
	}

	public void setPaginationLineColor(Color newColor) {
		this.paginationLineColor = newColor;
		this.worksheet.updateUI();
	}

	public Color getSelectedBackground() {
		return this.selectedBackground;
	}

	public void setSelectedBackground(Color selectedBackground) {
		this.selectedBackground = selectedBackground;
		this.worksheet.updateUI();
	}

	public Color getSelectedBorderLineColor() {
		return this.selectedBorderLineColor;
	}

	public void setSelectedBorderLineColor(Color newColor) {
		this.selectedBorderLineColor = newColor;
		this.worksheet.updateUI();
	}

	public boolean isEditable() {
		return this.editable;
	}

	public void setEditable(boolean editable) {
		this.editable = editable;
	}

	public boolean isSupportCellEditorDef() {
		return this.supportCellEditorDef;
	}

	public void setSupportCellEditorDef(boolean supportCellEditorDef) {
		this.supportCellEditorDef = supportCellEditorDef;
	}

	public boolean isCellDragable() {
		return this.cellDragable;
	}

	public void setCellDragable(boolean cellDragable) {
		this.cellDragable = cellDragable;
	}

	/**
	 * 是否正在编辑
	 * <p>
	 * 编辑器组件不为空
	 * 
	 * @return
	 */
	public boolean isEditing() {
		return (this.editorComponent != null);
	}

	/**
	 * 是否正在编辑单元格
	 * <p>
	 * 正在编辑且单元格编辑器不为空
	 * 
	 * @return
	 */
	public boolean isCellEditing() {
		return ((isEditing()) && (this.cellEditor != null));
	}

	/**
	 * 获取单元格编辑器
	 * 
	 * @param column
	 *            列
	 * @param row
	 *            行
	 * @return
	 */
	public CellEditor getCellEditor(int column, int row) {
		Cell cell = this.reportModel.getCell(column, row);

		if (cell instanceof DefaultCell) {
			return ((DefaultCell) cell).getCellEditor();
		} else {
			return null;
		}
	}

	public Component getEditorComponent() {
		return this.editorComponent;
	}

	/**
	 * 单元格是是否可编辑
	 * 
	 * @param column
	 *            列
	 * @param row
	 *            行
	 * @return 可编辑状态
	 */
	public boolean isCellEditable(int column, int row) {
		// CellReport report = this.worksheet.getReport();
		// CellElement cellElement = report.getCellElement(column, row);
		//
		// return ((cellElement != null) && (cellElement.getValue() instanceof
		// Component));
		return true;
	}

	public int getEditingColumn() {
		return this.editingColumn;
	}

	public void setEditingColumn(int editingColumn) {
		this.editingColumn = editingColumn;
	}

	public int getEditingRow() {
		return this.editingRow;
	}

	public void setEditingRow(int editingRow) {
		this.editingRow = editingRow;
	}

	public CellEditor getCellEditor() {
		return this.cellEditor;
	}

	public void setCellEditor(CellEditor cellEditor) {
		CellEditor oldEditor = this.cellEditor;
		this.cellEditor = cellEditor;
		firePropertyChange("CellEditor", oldEditor, this.cellEditor);
	}

	/**
	 * 获取Grid中显示的报表
	 * 
	 * @return
	 */
	public ReportModel getReport() {
		return this.worksheet.getReportModel();
	}

	/**
	 * 开始编辑
	 */
	public void startEditing() {
		startEditing(null);
	}

	/**
	 * 开始编辑单元格
	 * 
	 * @param keyEvent
	 */
	protected void startEditing(KeyEvent keyEvent) {
		if (isCellSelectable()) {
			Selection rect = this.worksheet.getGridSelection().getEditSelection();
			startCellEditingAt(rect.getColumn(), rect.getRow(), keyEvent);
		}
	}

	/**
	 * 开始单元格编辑
	 * 
	 * @param column
	 * @param row
	 * @return
	 */
	public void startCellEditingAt(int column, int row) {
		startCellEditingAt(column, row, null);
	}

	/**
	 * 开始单元格编辑
	 * 
	 * @param column
	 * @param row
	 * @param keyEvent
	 * @return
	 */
	private void startCellEditingAt(int column, int row, KeyEvent keyEvent) {
		if (isCellEditing()) {
			stopEditing();
		}

		if ((!isEditable()) || ((row < 0) || (column < 0)) || (!isCellEditable(column, row))) {
			return;
		}

		this.editingCell = this.reportModel.getCell(column, row);
		if (!(this.editingCell instanceof DefaultCell)) {
			this.reportModel.setCellValue(column, row, "");
			this.editingCell = this.reportModel.getCell(column, row);
		}

		this.cellEditor = ((DefaultCell) this.editingCell).getCellEditor();

		if (this.cellEditor == null) {
			this.editorComponent = null;
			return;
		}

		this.editorComponent = this.cellEditor.getCellEditorComponent(this, this.editingCell);

		if (this.editorComponent == null) {
			removeCellEditor();
			return;
		}

		this.cellEditor.addCellEditorListener(this.innerCellEditorListener);
		setCellEditor(this.cellEditor);
		setEditingColumn(column);
		setEditingRow(row);

		if (this.editorComponent instanceof Window) {
			SwingUtilities.invokeLater(new Runnable() {

				public void run() {
					if (Grid.this.editorComponent == null) {
						return;
					}
					Grid.this.editorComponent.setVisible(true);
				}
			});
		} else {
			if ((keyEvent != null) && (this.editorComponent instanceof JTextField)) {
				((JTextField) this.editorComponent).setText("");
			}

			if (this.editorComponent != null) {
				ajustEditorComponentBounds(this.worksheet, column, row);
				add(this.editorComponent);
			}

			validate();
			repaint(10L);
			if (this.editorComponent != null) {
				this.editorComponent.setVisible(true);
				this.editorComponent.requestFocus();
			}
		}
	}

	public void stopEditing() {
		stopCellEditingInner(true);
	}

	/**
	 * 停止单元格编辑
	 * 
	 * @param requestFocus
	 *            请求焦点
	 */
	private void stopCellEditingInner(boolean requestFocus) {
		Object cellValue;

		if (!isCellEditing()) {
			return;
		}

		CellEditor editor = this.cellEditor;
		if (editor == null) {
			if (this.editorComponent != null) {
				remove(this.editorComponent);
			}

			return;
		}

		ReportModel report = getReport();
		Object value = null;
		try {
			value = editor.getCellEditorValue();
		} catch (Exception ex) {
			logger.warn(ex.getMessage());
		}

		if (value == null) {
			removeCellEditor();
			return;
		}

		this.editingCell = (DefaultCell) report.getCell(this.editingColumn, this.editingRow);
		// if (this.editingCell.getClass() == VirtualCell.class) {
		// // TODO 修改
		// if (value instanceof String) {
		// if (!StringUtils.isEmpty(value)) {
		// this.editingCell.setValue(value);
		// }
		// } else {
		// this.editingCell.setValue(value);
		// }
		// } else {
		cellValue = this.editingCell.getValue();
		if (!(ComparatorUtils.equals_exactly(cellValue, value))) {
			this.editingCell.setValue(value);
			this.isDataChanged = true;
		}
		removeCellEditor();
		if (!requestFocus || hasFocus()) {
			return;
		}
		requestFocus();
	}

	public void cancelEditing() {
		if (!(isEditing())) {
			return;
		}

		removeCellEditor();
		requestFocus();

	}

	/**
	 * 移除单元格编辑器,
	 * <p>
	 * 每次编辑完成，移除编辑器
	 */
	public void removeCellEditor() {
		CellEditor editor = getCellEditor();
		if (editor == null) {
			return;
		}
		if (this.editorComponent != null) {
			if (this.editorComponent instanceof Window) {
				this.editorComponent.setVisible(false);
				((Window) this.editorComponent).dispose();
			} else {
				remove(this.editorComponent);
				validate();
			}
		}
		editor.removeCellEditorListener(this.innerCellEditorListener);
		setCellEditor(null);
		setEditingColumn(-1);
		setEditingRow(-1);
		this.editorComponent = null;
		this.editingCell = null;

		this.worksheet.updateUI();
	}

	@Override
	protected void processMouseMotionEvent(MouseEvent evt) {
		super.processMouseMotionEvent(evt);

		if (!isEnabled()) {
			return;
		}

		switch (evt.getID()) {
		case MouseEvent.MOUSE_MOVED:
			doMouseMoved(evt);
			break;

		case MouseEvent.MOUSE_DRAGGED:
			doMouseDragged(evt);
			break;
		}

	}

	/**
	 * 鼠标移动
	 * 
	 * @param mouseEvent
	 */
	private void doMouseMoved(final MouseEvent evt) {
		if (isEditing()) {
			return;
		}

		long lastTime = System.currentTimeMillis();
		if (lastTime - this.lastMouseMoveTime <= MOVE_REFRESH_TIME) {
			return;
		}

		this.lastMouseMoveTime = lastTime;
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {
				// TODO 处理mouseMoveOnGrid
				// mouseMoveOnGrid(evt.getX(), evt.getY());
			}
		});
	}

	// protected void mouseMoveOnGrid(int paramInt1, int paramInt2) {
	// this.tooltipText = null;
	// JWorkSheet localReportPane = this.worksheet;
	// CellReport localReport = localReportPane.getReport();
	// ColumnRow localColumnRow = GridUtils.getEventColumnRow(localReportPane,
	// paramInt1, paramInt2);
	//		
	// if ((localColumnRow.getRow() > localReport.getRowCount() - 1) ||
	// ((localColumnRow.getColumn() > localReport.getColumnCount() - 1))) {
	// setCursor(new Cursor(0));
	// return;
	//		
	// }
	// setCursor(GUIConstants.CURSOR_CELLDEFAULT);
	// int i = localColumnRow.getColumn();
	// int j = localColumnRow.getRow();
	// Cell localCellElement = localReport.getCell(i, j);
	// DynamicList localDynamicValueList1 = localReport.getColumnWidthList();
	// DynamicList localDynamicValueList2 = localReport.getRowHeightList();
	// double d1 = -1.0D;
	// double d2 = -1.0D;
	// if (localCellElement.getElement() != null) {
	// // CellGUIAttr localCellGUIAttr = localCellElement.getCellGUIAttr();
	// // if (localCellGUIAttr == null) {
	// // localCellGUIAttr = CellGUIAttr.DEFAULT_CELLGUIATTR;
	// // }
	// // this.tooltipText = localCellGUIAttr.getTooltipText();
	// d1 = localDynamicValueList1.getRangeValue(0,
	// localCellElement.getColumn()) + 4.0D;
	// d2 =
	// localDynamicValueList2.getRangeValue(0, localCellElement.getRow() +
	// localCellElement.getRowSpan()) + 4.0D;
	// // if (localCellGUIAttr.getEditableState() == 0) {
	// // if (!(localReport.getReportGUIAttr().isEditable())) {
	// // setCursor(new Cursor(0));
	// // } else if (localCellGUIAttr.getEditableState() == 2) {
	// // setCursor(new Cursor(0));
	// // }
	// // }
	// double d3 = paramInt1 - (localDynamicValueList1.getRangeValue(0,
	// localCellElement.getColumn()));
	// double d4 = paramInt2 - (localDynamicValueList2.getRangeValue(0,
	// localCellElement.getRow()));
	// int l = 6;
	// int i1 = 0;
	//		
	// int i2 =
	// localDynamicValueList1.getRangeValue(localCellElement.getColumn(),
	// localCellElement.getColumn() + localCellElement.getColumnSpan());
	// int i3 = localDynamicValueList2.getRangeValue(localCellElement.getRow(),
	// localCellElement.getRow() + localCellElement.getRowSpan());
	// // if ((localCellElement.getCellEditorDef() != null) && (d3 > 0.0D) &&
	// (i3 - d4 > 0.0D) && (d3 + i3 - d4 < l)) {
	// // setCursor(new Cursor(0));
	// // this.tooltipText = "wwwwwwwwwwwww";
	// // d1 = paramInt1 - d3 - 10.0D;
	// // d2 = paramInt2 - d4 + i3 + 20.0D;
	// // }
	// Object localObject = localCellElement.getElement().getValue();
	// int k = isMoveCellSelection(paramInt1, paramInt2);
	// if (k == GridUtils.DRAG_CELLSELECTION) {
	// setCursor(new Cursor(13));
	// } else if (k == GridUtils.DRAG_CELLSELECTION_BOTTOMRIGHT_CORNER) {
	// setCursor(new Cursor(1));
	// }
	//		
	// if ((this.tooltipText == null) || (this.tooltipText.length() <= 0)) {
	// return;
	// }
	//		
	// this.tooltipLocation.setLocation(d1, d2);
	// } else {
	// setCursor(Cursor.getDefaultCursor());
	// }
	// }

	/**
	 * 处理鼠标拖动
	 * 
	 * @param evt
	 *            鼠标事件
	 */
	private void doMouseDragged(MouseEvent evt) {
		if (isEditing()) {
			return;
		}

		if (SwingUtilities.isRightMouseButton(evt)) {
			return;
		}

		long lastTime = System.currentTimeMillis();
		if (lastTime - this.lastMouseMoveTime <= DRAG_REFRESH_TIME) {
			return;
		}

		this.lastMouseMoveTime = lastTime;

		threadMouseDragged(this.worksheet, evt.getX(), evt.getY(), evt.isControlDown());
	}

	@Override
	protected void processMouseWheelEvent(MouseWheelEvent evt) {
		switch (evt.getID()) {
		case MouseEvent.MOUSE_WHEEL:
			int pos = evt.getWheelRotation();
			this.worksheet.getVerScrollBar().setValue(this.worksheet.getVerScrollBar().getValue() + pos * 3);
		}
	}

	@Override
	protected void processComponentKeyEvent(KeyEvent evt) {
		if (!isEnabled() || !isCellSelectable()) {
			return;
		}

		if (evt.isConsumed()) {
			return;
		}

		KeyEvent keyEvt = KeyEventUtils.processKeyEvent(evt);
		if (keyEvt == null) {
			return;
		}

		switch (keyEvt.getID()) {
		case KeyEvent.KEY_FIRST:
			doKeyTyped(keyEvt);
			break;

		case KeyEvent.KEY_PRESSED:
			doKeyPressed(keyEvt);
			break;

		case KeyEvent.KEY_LAST:
			if (!(this.isKeyPressedContentChanged)) {
				return;
			}

			this.isKeyPressedContentChanged = false;
		}

	}

	private void doKeyTyped(KeyEvent evt) {
		if (evt.isControlDown()) {
			return;
		}

		char keyChar = evt.getKeyChar();

		if (!Character.isDefined(keyChar)) {
			return;
		}

		if (!isCellEditing()) {
			startEditing(evt);
		}

		if ((this.cellEditor == null) || (this.editorComponent == null)) {
			return;
		}

		if (evt.isConsumed()) {
			return;
		}

		this.editorComponent.dispatchEvent(evt);
	}

	private void doKeyPressed(KeyEvent evt) {
		long lastTime = System.currentTimeMillis();
		int keyCode = evt.getKeyCode();
		int j = 0;

		if (lastTime - this.keyPressedLastTime <= 32L) {
			return;
		}
		this.keyPressedLastTime = lastTime;

		switch (keyCode) {
		case KeyEvent.VK_ESCAPE:
			if (isCellEditing()) {
				cancelEditing();
			}

			break;
		case KeyEvent.VK_F2:
			if (!(isCellEditing())) {
				startEditing();
			}

		}

		this.worksheet.repaint();
	}

	@Override
	protected void processMouseEvent(MouseEvent evt) {
		super.processMouseEvent(evt);

		if (!isEnabled()) {
			return;
		}

		switch (evt.getID()) {
		case MouseEvent.MOUSE_EXITED:
			break;
		case MouseEvent.MOUSE_ENTERED:
			break;
		case MouseEvent.MOUSE_PRESSED:
			doMousePress(evt);
			break;
		case MouseEvent.MOUSE_RELEASED:
			doMouseReleased(evt);
			break;
		}
	}

	/**
	 * 鼠标按下处理
	 * 
	 * @param x
	 * @param y
	 */
	public void doMousePress(double x, double y) {
		MouseEvent mouseEvent = new MouseEvent(this, 100, 1L, 0, (int) x, (int) y, 1, false, MouseEvent.BUTTON1);
		doMousePress(mouseEvent);
	}

	/**
	 * 鼠标按下处理
	 * 
	 * @param evt
	 *            鼠标事件
	 */
	private void doMousePress(MouseEvent evt) {
		stopEditing();

		if (!hasFocus() && isRequestFocusEnabled()) {
			requestFocus();
		}

		int xPos = evt.getX();
		int yPos = evt.getY();
		oldEvtX = xPos;
		oldEvtY = yPos;
		dragType = GridUtils.DRAG_NONE;

		doOneClickSelection(worksheet, evt);

		if (SwingUtilities.isRightMouseButton(evt)) {
			showPopupMenu(evt);
		} else {
			if (evt.getClickCount() >= 2) {
				startEditing();
			}
		}

		worksheet.repaint();
	}

	/**
	 * 释放鼠标
	 * 
	 * @param evt
	 *            鼠标事件
	 */
	private void doMouseReleased(MouseEvent evt) {
		if (!isEditable()) {
			return;
		}

		boolean bDirectExit = false;
		JWorksheet worksheet = this.worksheet;
		GridSelection gridSel = worksheet.getGridSelection();

		if (gridSel == null) {
			return;
		}

		if (this.dragType == GridUtils.DRAG_CELLSELECTION) {// 拖动选择单元
		} else if (this.dragType == GridUtils.DRAG_CELLSELECTION_BOTTOMRIGHT_CORNER) {// 拖动选择框角落
		}
		this.dragType = GridUtils.DRAG_NONE;
		this.dragRectangle = null;

		if (!(bDirectExit)) {
			return;
		}

		worksheet.repaint();
	}

	/**
	 * 鼠标拖动处理
	 * 
	 * @param workSheet
	 *            工作sheet
	 * @param x
	 *            x位置
	 * @param y
	 *            y位置
	 * @param isCtlDown
	 *            Ctl是否按下
	 */
	protected void threadMouseDragged(JWorksheet workSheet, int x, int y, boolean isCtlDown) {
		GridSelection gridSel = workSheet.getGridSelection();
		boolean needUpdate = false;

		if (this.dragType == GridUtils.DRAG_CELLSELECTION_BOTTOMRIGHT_CORNER) {
		} else if (this.dragType == GridUtils.DRAG_CELLSELECTION) {// 拖动选择区
		} else if (isCellSelectable()) {// 拖动选择单元格
			Selection sel = gridSel.getLastCellSelection();
			doShiftSelectCell(workSheet, x, y, sel);
			needUpdate = true;
		}

		if (needUpdate) {
			this.worksheet.refresh();
		}
	}

	/*
	 * 转换单元格选择
	 */
	private void doShiftSelectCell(JWorksheet worksheet, double x, double y, Selection selRect) {
		ColumnRow cr = WorksheetUtils.getAdjustEventColumnRow(worksheet, x, y);
		GridSelection gridSel = worksheet.getGridSelection();
		Selection sel = gridSel.getEditSelection();

		int curX = sel.getColumn();
		int curY = sel.getRow();

		Selection rectSel = new Selection(Math.min(curX, cr.getColumn()), Math.min(curY, cr.getRow()), Math.max(sel
				.getColumSpan(), Math.abs(curX - cr.getColumn()) + 1), Math.max(sel.getRowSpan(), Math.abs(curY
				- cr.getRow()) + 1));

		selRect.setBounds(rectSel.getColumn(), rectSel.getRow(), rectSel.getColumSpan(), rectSel.getRowSpan());
	}

	/**
	 * 处理单元格选择
	 * 
	 * @param workSheet
	 *            工作薄
	 * @param x
	 *            x位置
	 * @param y
	 *            y位置
	 * @param isShiftDown
	 *            Shift按下
	 * @param isCtlDown
	 *            Ctl按下
	 */
	private void doOneClickSelection(JWorksheet workSheet, MouseEvent evt) {
		int x = evt.getX();
		int y = evt.getY();
		boolean isShiftDown = evt.isShiftDown();
		boolean isCtlDown = evt.isControlDown();

		GridSelection gridSel = workSheet.getGridSelection();
		if (gridSel == null) {
			return;
		}

		if (isCellSelectable()) {
			gridSel.setType(GridSelection.Type.CELL);
			ColumnRow cr = WorksheetUtils.getColumnRowByXY(workSheet, x, y);
			Selection sel = null;

			if (isShiftDown) {
				if (isCtlDown) {
					sel = gridSel.getLastCellSelection();
				} else {
					sel = gridSel.getFirstCellSelection();
				}

				doShiftSelectCell(workSheet, x, y, sel);
				workSheet.fireGridSelectionChanged();
				return;
			} else if (isCtlDown) {
				doControlSelectCell(workSheet, x, y);
				workSheet.fireGridSelectionChanged();
				return;
			}

			GridUtils.doSelectCell(workSheet, cr.getColumn(), cr.getRow());

			return;

		}

		gridSel.setType(GridSelection.Type.CELL);
		gridSel.clearAllCellSelections();
		gridSel.clearAllFloatName();

		workSheet.fireGridSelectionChanged();
	}

	@Override
	public String getToolTipText(MouseEvent paramMouseEvent) {
		return this.tooltipText;
	}

	@Override
	public Point getToolTipLocation(MouseEvent paramMouseEvent) {
		if ((this.tooltipText != null) && (this.tooltipText.length() > 0)) {
			return this.tooltipLocation;
		}

		return null;
	}

	@Override
	public void paintComponent(Graphics g) {
		if (isPainting || (this.reportModel == null)) {
			return;
		}

		isPainting = true;

		Graphics2D g2 = (Graphics2D) g;
		JWorksheet worksheet = this.worksheet;

		// 填充背景
		Dimension dim = getSize();
		this.tmpRectangle2D.setRect(0.0D, 0.0D, dim.getWidth(), dim.getHeight());
		if (isEnabled()) {
			g2.setPaint(Color.WHITE);
		} else {
			g2.setPaint(UIManager.getColor("control"));
		}
		g2.fill(this.tmpRectangle2D);

		g2.setColor(this.gridLineColor);
		g2.draw(this.tmpRectangle2D);

		ColumnPropList cpl = this.reportModel.getColumnPropList();
		RowPropList crl = this.reportModel.getRowPropList();

		this.drawGridLine(g2, dim, cpl, crl);

		// 绘制对象
		for (int i = 0, colCount = worksheet.getHoriValueExtend(); i < colCount; i++) {
			int column = worksheet.getHoriBeginValue() + i;
			for (int j = 0, rowCount = worksheet.getVertValueExtend(); j < rowCount; j++) {
				int row = worksheet.getVertBeginValue() + j;

				worksheet.paintCell(g2, column, row);
				// worksheet.paintCellElementFlag(g2, column, row);
			}
		}

		// --绘制选中区域 开始--
		GridSelection gridSel = worksheet.getGridSelection();
		Composite oldComposite = g2.getComposite();
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5F));
		g2.setPaint(getSelectedBackground());
		for (int i = 0; i < gridSel.getCellSelectionCount(); i++) {
			Selection sel = gridSel.getCellSelection(i);
			Rectangle rect = this.reportModel.getCellRectangle(this.worksheet, sel);

			tmpRectangle2D.setRect(rect.x, rect.y, rect.width, rect.height);
			GraphHelper.fill(g2, tmpRectangle2D);
		}
		g2.setComposite(oldComposite);

		Selection sel = gridSel.getEditSelection();
		Rectangle rect = reportModel.getCellRectangle(this.worksheet, sel);
		tmpRectangle2D.setRect(rect.x + 2, rect.y + 2, rect.width - 3, rect.height - 3);
		g2.setPaint(Color.WHITE);
		GraphHelper.fill(g2, tmpRectangle2D);

		worksheet.paintCell(g2, sel.getColumn(), sel.getRow(), getSelectedBorderLineColor());
		worksheet.paintCellElementFlag(g2, sel.getColumn(), sel.getRow());

		if (gridSel.getCellSelectionCount() == 1) {
			Selection sel1 = gridSel.getLastCellSelection();
			Rectangle rect1 = this.reportModel.getCellRectangle(this.worksheet, sel);
			tmpRectangle2D.setRect(rect1.x, rect1.y, rect1.width, rect1.height);
			g2.setPaint(getSelectedBorderLineColor());
			GraphHelper.draw(g2, tmpRectangle2D, 5);
		} else {
			Selection sel2 = gridSel.getLastCellSelection();
			Rectangle rect2 = this.reportModel.getCellRectangle(this.worksheet, sel);
			tmpRectangle2D.setRect(rect2.x, rect2.y, rect2.width, rect2.height);
			g2.setPaint(getSelectedBorderLineColor());
			GraphHelper.draw(g2, tmpRectangle2D, 1);
		}
		// --绘制选中区域 结束--

		isPainting = false;
	}

	// 绘制网格线
	private void drawGridLine(Graphics2D g2, Dimension dim, ColumnPropList cpl, RowPropList crl) {
		if (!this.showGridLine) {
			return;
		}

		// 绘制行线
		g2.setColor(getGridLineColor());

		double perLen = 0.0D;
		double preLen = 0.0D;
		double nextLen = 0.0D;
		double h = dim.getHeight();
		double w = dim.getWidth();
		int row = worksheet.getVertBeginValue();
		while (nextLen < h) {
			preLen += perLen;
			perLen = crl.getValue(row++);
			if (perLen < 0.001D) {
				nextLen = preLen + 1.0D;
			} else {
				nextLen = preLen + perLen;
			}

			GraphHelper.drawLine(g2, 0.0D, nextLen, w, nextLen);
		}

		// 绘制列线
		perLen = 0;
		preLen = 0;
		nextLen = 0;
		h = dim.getHeight();
		w = dim.getWidth();
		int column = worksheet.getHoriBeginValue();
		while (nextLen < w) {
			preLen += perLen;
			perLen = cpl.getValue(column++);
			if (perLen < 0.001D) {
				nextLen = preLen + 1.0D;
			} else {
				nextLen = preLen + perLen;
			}

			GraphHelper.drawLine(g2, nextLen, 0.0D, nextLen, h);
		}
	}

	// private void paintTableCellElementTip(Graphics2D paramGraphics2D, double
	// paramDouble1, double paramDouble2,
	// String paramString, LineMetrics paramLineMetrics) {
	// GeneralPath localGeneralPath = new GeneralPath(1);
	// localGeneralPath.moveTo(0.0F, 0.0F);
	// paramDouble1 += ToolTipLeftDistance;
	// double d = paramDouble2 / 2.0D;
	// if (d <= ToolTipLeftDistance) {
	// localGeneralPath.lineTo((float) d, (float) d);
	// } else {
	// localGeneralPath.lineTo(ToolTipLeftDistance, ToolTipLeftDistance);
	// localGeneralPath.lineTo(ToolTipLeftDistance, (float) paramDouble2 -
	// ToolTipLeftDistance);
	// }
	//
	// localGeneralPath.lineTo(0.0F, (float) paramDouble2);
	// localGeneralPath.lineTo((float) paramDouble1, (float) paramDouble2);
	// localGeneralPath.lineTo((float) paramDouble1, 0.0F);
	// localGeneralPath.lineTo(0.0F, 0.0F);
	// paramGraphics2D.setPaint(new Color(212, 208, 200));
	// // GraphHelper.fill(paramGraphics2D, localGeneralPath);
	// // paramGraphics2D.setPaint(Color.gray);
	// // GraphHelper.draw(paramGraphics2D, localGeneralPath);
	// // paramGraphics2D.setPaint(Color.black);
	// // GraphHelper.drawString(paramGraphics2D, paramString,
	// // ToolTipLeftDistance + 2, (paramDouble2 -
	// // paramLineMetrics.getHeight()) / 2.0D + paramLineMetrics.getAscent());
	// }

	/**
	 * 按下Control键时选择单元格
	 * 
	 * @param workSheet
	 *            工作薄
	 * @param x
	 *            x位置
	 * @param y
	 *            y位置
	 */
	private void doControlSelectCell(JWorksheet workSheet, double x, double y) {
		ReportModel report = workSheet.getReportModel();
		GridSelection gridSel = workSheet.getGridSelection();
		gridSel.setType(GridSelection.Type.CELL);
		ColumnRow columnRow = WorksheetUtils.getAdjustEventColumnRow(workSheet, x, y);
		Cell cell = report.getCell(columnRow.getColumn(), columnRow.getRow());
		gridSel.setEditBounds(cell.getColumn(), cell.getRow(), cell.getColumnSpan(), cell.getRowSpan());
		gridSel
				.addCellSelection(new Selection(cell.getColumn(), cell.getRow(), cell.getColumnSpan(), cell
						.getRowSpan()));
		// TODO 控制可见性
	}

	protected boolean shiftUp(JWorksheet paramReportPane, Selection paramRectangle1, Selection paramRectangle2) {
		// Rectangle localRectangle1;
		// Rectangle localRectangle2;
		//
		// ReportModel localReport = paramReportPane.getReportModel();
		// int i = paramRectangle1.y + paramRectangle1.height - 1;
		// int j = paramRectangle2.y + paramRectangle2.height - 1;
		// if (j > i) {
		// localRectangle1 = caculateIntersectsUnion(localReport, new
		// Rectangle(paramRectangle2.x, j,
		// paramRectangle2.width, 1));
		// if (ReportUtils.contains(localRectangle1.x, localRectangle1.y,
		// localRectangle1.width,
		// localRectangle1.height, paramRectangle1.x, paramRectangle1.y,
		// paramRectangle1.width,
		// paramRectangle1.height)) {
		// if (paramRectangle2.y <= 0) {
		// return false;
		// }
		//
		// localRectangle2 = caculateIntersectsUnion(localReport, new
		// Rectangle(paramRectangle2.x,
		// paramRectangle2.y - 1, paramRectangle2.width, paramRectangle2.height
		// + 1));
		// Rectangle localRectangle3 = localRectangle2.union(new
		// Rectangle(paramRectangle2.x, paramRectangle2.y,
		// paramRectangle2.width, paramRectangle2.height));
		// paramRectangle2.setBounds(localRectangle3.x, localRectangle3.y,
		// localRectangle3.width,
		// localRectangle3.height);
		// } else {
		// paramRectangle2.height = (localRectangle1.y - paramRectangle2.y);
		// }
		//
		// } else {
		// if (paramRectangle2.y <= 0) {
		// return false;
		// }
		//
		// localRectangle1 = caculateIntersectsUnion(localReport, new
		// Rectangle(paramRectangle2.x,
		// paramRectangle2.y - 1, paramRectangle2.width, paramRectangle2.height
		// + 1));
		// localRectangle2 = localRectangle1.union(new
		// Rectangle(paramRectangle2.x, paramRectangle2.y,
		// paramRectangle2.width, paramRectangle2.height));
		// paramRectangle2.setBounds(localRectangle2.x, localRectangle2.y,
		// localRectangle2.width,
		// localRectangle2.height);
		// }

		return true;
	}

	protected boolean shiftDown(JWorksheet paramReportPane, Selection paramRectangle1, Selection paramRectangle2) {
		// Rectangle localRectangle1;
		// Rectangle localRectangle2;
		//
		// ReportModel localReport = paramReportPane.getReportModel();
		// if (paramRectangle2.y < paramRectangle1.y) {
		// localRectangle1 = caculateIntersectsUnion(localReport, new
		// Rectangle(paramRectangle2.x, paramRectangle2.y,
		// paramRectangle2.width, 1));
		// if (ReportUtils.contains(localRectangle1.x, localRectangle1.y,
		// localRectangle1.width,
		// localRectangle1.height, paramRectangle1.x, paramRectangle1.y,
		// paramRectangle1.width,
		// paramRectangle1.height)) {
		// if ((paramRectangle2.y + paramRectangle2.height >
		// localReport.getRowCount() - 1)) {
		// return false;
		// }
		//
		// localRectangle2 = caculateIntersectsUnion(localReport, new
		// Rectangle(paramRectangle2.x,
		// paramRectangle2.y, paramRectangle2.width, paramRectangle2.height +
		// 1));
		// Rectangle localRectangle3 = localRectangle2.union(new
		// Rectangle(paramRectangle2.x, paramRectangle2.y,
		// paramRectangle2.width, paramRectangle2.height));
		// paramRectangle2.setBounds(localRectangle3.x, localRectangle3.y,
		// localRectangle3.width,
		// localRectangle3.height);
		// } else {
		// paramRectangle2.height = (paramRectangle2.y + paramRectangle2.height
		// - (localRectangle1.y + localRectangle1.height));
		// paramRectangle2.y = (localRectangle1.y + localRectangle1.height);
		// }
		//
		// } else {
		// if ((paramRectangle2.y + paramRectangle2.height >
		// localReport.getRowCount() - 1)) {
		// return false;
		// }
		//
		// localRectangle1 = caculateIntersectsUnion(localReport, new
		// Rectangle(paramRectangle2.x, paramRectangle2.y,
		// paramRectangle2.width, paramRectangle2.height + 1));
		// localRectangle2 = localRectangle1.union(new
		// Rectangle(paramRectangle2.x, paramRectangle2.y,
		// paramRectangle2.width, paramRectangle2.height));
		// paramRectangle2.setBounds(localRectangle2.x, localRectangle2.y,
		// localRectangle2.width,
		// localRectangle2.height);
		// }

		return true;
	}

	/**
	 * 调整编辑控件位置
	 * 
	 * @param workSheet
	 *            工作薄
	 * @param column
	 *            列
	 * @param row
	 *            行
	 */
	private void ajustEditorComponentBounds(JWorksheet workSheet, int column, int row) {
		if ((this.editorComponent == null) || (this.editorComponent instanceof Window)) {
			return;
		}

		ReportModel report = workSheet.getReportModel();
		// Cell cell = report.getMergedToCell(column, row);
		Cell cell = report.getCell(column, row);

		RowPropList rhl = report.getRowPropList();
		ColumnPropList cwl = report.getColumnPropList();

		int left;
		int top;
		int width;
		int height;
		left = cwl.getRangeValue(workSheet.getHoriBeginValue(), cell.getColumn());
		top = rhl.getRangeValue(workSheet.getVertBeginValue(), cell.getRow());
		width = cwl.getRangeValue(cell.getColumn(), cell.getColumn() + cell.getColumnSpan()) - 1;
		height = rhl.getRangeValue(cell.getRow(), cell.getRow() + cell.getRowSpan()) - 1;

		this.editorComponent.setLocation(left + 1, top + 1);
		if (this.editorComponent instanceof JTextField) {
			Dimension dim = this.editorComponent.getPreferredSize();
			this.editorComponent.setSize((int) Math.max(width, dim.getWidth() + 1), height);
		} else {
			this.editorComponent.setSize(width, height);
		}

	}

	public int getEnterMoveDirection() {
		return this.enterMoveDirection;
	}

	public void setEnterMoveDirection(int paramInt) {
		this.enterMoveDirection = paramInt;
	}

	public int getTabMoveDirection() {
		return this.tabMoveDirection;
	}

	public void setTabMoveDirection(int paramInt) {
		this.tabMoveDirection = paramInt;
	}

	public boolean isCellSelectable() {
		return this.cellSelectable;
	}

	public void setCellSelectable(boolean paramBoolean) {
		boolean bool = this.cellSelectable;
		this.cellSelectable = paramBoolean;
		firePropertyChange("cellSelectable", bool, this.cellSelectable);
		this.worksheet.updateUI();
		this.cellSelectable = paramBoolean;
	}

	/**
	 * @return 行总数
	 */
	public int getColumnCount() {
		return this.worksheet.getColumnCount();
	}

	/**
	 * @return 列总数
	 */
	public int getRowCount() {
		return this.worksheet.getRowCount();
	}

	/**
	 * 显示弹出菜单
	 * 
	 * @param evt
	 */
	private void showPopupMenu(MouseEvent evt) {
		if (this.gridActionMenu != null) {
			this.gridActionMenu.show(this, evt.getX(), evt.getY());
		}
	}

	/**
	 * 设置功能菜单
	 * 
	 * @param gridActionMenu
	 *            功能菜单
	 */
	public void setGridActionMenu(JPopupMenu gridActionMenu) {
		this.gridActionMenu = gridActionMenu;
	}

	// public JToolTip createToolTip() {
	// ScrollToolTip localScrollToolTip = new ScrollToolTip();
	// localScrollToolTip.setComponent(this);
	// return localScrollToolTip;
	// }
}
